package com.itita.ww2.redis.sort;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itita.ww2.redis.RedisUtil;
import com.itita.ww2.redis.core.Redis;
import com.lambdaworks.redis.KeyValue;
import com.lambdaworks.redis.ScoredValue;
import com.lambdaworks.redis.api.sync.RedisCommands;

/**
 * 排序,使用sortedset进行排序
 * 实现 物理分页/名次查询
 * @author NorthLan
 *
 */
public class Sort {
	private static final Logger logger = LoggerFactory.getLogger(Sort.class);
	// 
	private static final String PREFIX = "sort";

	private Redis redis;
	private String key;
	private String sortedField;

	public Sort(Redis redis, String key, String sortedField) {
		this.redis = redis;
		this.sortedField = sortedField;
		this.key = RedisUtil.combineKey(PREFIX, key, sortedField);
	}

	public Sort(Redis redis, String key) {
		this(redis, key, null);
	}

	/**
	 * 添加排序项
	 * @param score 用于排序的数据
	 */
	public void add(String member, double score) {
		redis.getRedisCmd().zadd(key, score, member);
	}

	public void add(String member, String score) {
		if (RedisUtil.isDouble(score)) {
			add(member, Double.parseDouble(score));
		} else {
			logger.warn("Member: [{},{}] isn't a number, set 0", member, score);
			add(member, 0);
		}
	}

	/**
	 * 移除排序项
	 */
	public void remove(String member) {
		redis.getRedisCmd().zrem(key, member);
	}

	/**
	 * 排序
	 * @param page 页码,由1开始
	 * @param pageCount 每页数量
	 * @param desc 是否降序
	 * @return 排序过的members
	 */
	public List<ScoredValue<String>> sort(int page, int pageCount, boolean desc) {
		RedisCommands<String, String> cmd = redis.getRedisCmd();
		if (desc) {
			return cmd.zrevrangeWithScores(key, (page - 1) * pageCount, pageCount == -1 ? -1 : (page * pageCount) - 1);
		} else {
			return cmd.zrangeWithScores(key, (page - 1) * pageCount, pageCount == -1 ? -1 : (page * pageCount) - 1);
		}
	}

	/**
	 * 查询指定member的排名
	 * @param member 指定member
	 * @param desc <br>降序:分值越高,排名越高<br>升序:分值越低,排名越低
	 */
	public KeyValue<Integer, Double> rank(String member, boolean desc) {
		KeyValue<Integer, Double> ref;
		RedisCommands<String, String> cmd = redis.getRedisCmd();
		if (desc) {
			Long r = cmd.zrevrank(key, member);
			int rank = r == null ? -1 : r.intValue();
			Double s = cmd.zscore(key, member);
			double score = s == null ? 0 : s.doubleValue();

			ref = new KeyValue<Integer, Double>(rank, score);
		} else {
			Long r = cmd.zrank(key, member);
			int rank = r == null ? -1 : r.intValue();
			Double s = cmd.zscore(key, member);
			double score = s == null ? 0 : s.doubleValue();

			ref = new KeyValue<Integer, Double>(rank, score);
		}
		return ref;
	}

	public String getSortedField() {
		return sortedField;
	}
}
